home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / dbg / sun4c.md / dbgMain.c < prev    next >
C/C++ Source or Header  |  1991-06-28  |  30KB  |  1,208 lines

  1. /* dbgMain.c -
  2.  *
  3.  *     This contains the routines which read and execute commands from kdbx.
  4.  *
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/kernel/dbg/sun4.md/RCS/dbgMain.c,v 9.12 91/06/28 12:09:22 mgbaker Exp $ SPRITE (Berkeley)";
  18. #endif not lint
  19.  
  20. #include <sprite.h>
  21. #include <dbg.h>
  22. #include <dbgInt.h>
  23. #include <main.h>
  24. #include <mach.h>
  25. #include <proc.h>
  26. #ifndef FIRST_RUN
  27. #include <vm.h>
  28. #include <vmInt.h>
  29. #include <vmMach.h>
  30. #include <vmMachInt.h>
  31. #endif
  32. #include <machMon.h>
  33. #include <net.h>
  34. #include <netEther.h>
  35. #include <netInet.h>
  36. #include <dev.h>
  37. #include <devVid.h>
  38. #include <stdio.h>
  39. #include <bstring.h>
  40. #include <string.h>
  41.  
  42. Boolean dbg_InDebugger = FALSE;            /* TRUE if we are currently in
  43.                          * the debug command loop. */
  44. Boolean    dbg_BeingDebugged = FALSE;        /* TRUE if are under control
  45.                          * of kdbx or kgdb.*/
  46. Boolean    dbg_UsingNetwork = FALSE;        /* TRUE if the debugger is
  47.                          * using the network interface*/
  48. char    requestBuffer[DBG_MAX_REQUEST_SIZE];    /* Buffer to receive request
  49.                          * into. */
  50. int    requestOffset;                /* Offset in buffer where next
  51.                          * bytes should be read from.*/
  52. char    replyBuffer[DBG_MAX_REPLY_SIZE+2];    /* Buffer to hold reply. */
  53. int    replyOffset = 0;            /* Offset in buffer where next
  54.                          * bytes in reply should go. */
  55. int    curMsgNum;                /* The current message that
  56.                          * is being processed. */
  57. int    dbgMonPC;                /* Place to get the PC from
  58.                          * if trap via the monitor.*/
  59. int    dbgTraceLevel;                /* The debugger tracing
  60.                          * level. */
  61. Boolean    dbg_Rs232Debug = FALSE;            /* TRUE if we are using the
  62.                          * RS@#@ line to debug.  FALSE
  63.                          * if we are using the network.
  64.                          * On the sun4, we have only
  65.                          * used the network.
  66.                          */
  67. Boolean    dbg_SyncedDisks = FALSE;        /* For determining in the
  68.                          * debugger whether the disks
  69.                          * got sync'd or not. */
  70.  
  71. /*
  72.  * Number of times to poll before timing out and resending (about 2 seconds).
  73.  */
  74. #ifdef sun3
  75. int    dbgTimeout = 50000;
  76. #endif
  77. #ifdef sun2
  78. int    dbgTimeout = 15000;
  79. #endif
  80. #ifdef sun4
  81. int    dbgTimeout = 150000;
  82. #endif
  83.  
  84. /*
  85.  * Information about the latest packet received.
  86.  */
  87. Boolean            gotPacket;    
  88. int            dbgPacketLength;
  89. Net_InetAddress        dbgMyIPAddr;
  90. Net_InetAddress        dbgSrcIPAddr;
  91. Net_InetAddress        dbgSrcPort;
  92. Net_EtherHdr        dbgEtherHdr;
  93. Net_ScatterGather    dbgGather;
  94. Net_Interface        *dbgInterPtr = (Net_Interface *) NIL;
  95.  
  96. /*
  97.  * Size of debugging packet header and data.
  98.  */
  99. #define    PACKET_HDR_SIZE (sizeof(Net_EtherHdr) + Dbg_PacketHdrSize() + 4 + 2)
  100. #define PACKET_DATA_SIZE (DBG_MAX_REPLY_SIZE - PACKET_HDR_SIZE)
  101.  
  102. /*
  103.  * Strings which describe each of the opcodes that kdbx can send us.
  104.  */
  105. static char *opcodeNames[] = DBG_OPCODE_NAMES ;
  106.  
  107. /*
  108.  * Strings which describe the different exceptions that can occur.
  109. */
  110. static char *exceptionNames[] = DBG_EXECPTION_NAMES ;
  111.  
  112. /*
  113.  * The type of machine that we are on.
  114.  */
  115. int        machineType;
  116.  
  117. /*
  118.  * Whether syslog should remain diverted on continue or not.
  119.  */
  120. static Boolean    syslogDiverted = FALSE;
  121.  
  122. /*
  123.  * Declare global variables.
  124.  */
  125. int        dbgSfcReg;
  126. int        dbgDfcReg;
  127. int         dbgUserContext;
  128. int         dbgKernelContext;
  129. int        dbgTermReason;
  130. int        dbgInDebugger;
  131. int        dbgIntPending;
  132. int        dbgExcType;
  133. Boolean        dbgPanic;
  134. int        dbgSavedSP;
  135. int        dbgMaxStackAddr;
  136. Boolean        dbg_UsingSyslog = FALSE;
  137. Boolean        dbgCanUseSyslog = TRUE;
  138. static       int    oldContext;
  139.  
  140.  
  141. /* 
  142.  * Forward declarations:
  143.  */
  144. static void DbgCheckNmis _ARGS_((void));
  145. static char *    TranslateOpcode _ARGS_((Dbg_Opcode opcode));
  146. static char *    TranslateException _ARGS_((int exception));
  147. static Boolean    ReadRequest _ARGS_((Boolean timeout));
  148. static void    SendReply _ARGS_((void));
  149. static void    GetRequestBytes _ARGS_((int numBytes, Address dest));
  150. static void    PutReplyBytes _ARGS_((int numBytes, Address src));
  151.  
  152.  
  153. /*
  154.  * ----------------------------------------------------------------------------
  155.  *
  156.  * DbgCheckNmis --
  157.  *
  158.  *    Turn Non-maskable-interrupts on and off to allow keyboard events to
  159.  *    take place.  Only needed on Sun-2's because of the funny mapping
  160.  *    between kernel and user address spaces - they are turned on in the
  161.  *    main debugging loop on Sun-3's.
  162.  *
  163.  * Results:
  164.  *     None.
  165.  *
  166.  * Side effects:
  167.  *     None.
  168.  *
  169.  * ----------------------------------------------------------------------------
  170.  */
  171. static void
  172. DbgCheckNmis()
  173. {
  174. #ifdef sun2
  175.     int    oldContext;
  176.     oldContext = VmMachGetKernelContext(); 
  177.     VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  178.     Mach_MonStartNmi();
  179.     Mach_MonStopNmi();
  180.     VmMachSetKernelContext(oldContext);
  181. #endif
  182. }
  183.  
  184.  
  185. /*
  186.  * ----------------------------------------------------------------------------
  187.  *
  188.  * Dbg_InRange --
  189.  *
  190.  *     Return true if the given address is a valid kernel address and false
  191.  *     otherwise.
  192.  *
  193.  * Results:
  194.  *     True if the given address is a valid kernel address and false
  195.  *     otherwise.
  196.  *
  197.  * Side effects:
  198.  *     None.
  199.  *
  200.  * ----------------------------------------------------------------------------
  201.  */
  202. Boolean
  203. Dbg_InRange(addr, numBytes, writeable) 
  204.     unsigned     int addr;     /* Beginning address to check. */
  205.     int        numBytes;     /* Number of bytes to check. */
  206.     Boolean    writeable;    /* TRUE => address must be writeable. */
  207. {
  208. #ifndef FIRST_RUN
  209.     VmMachPTE        pte;
  210. #endif
  211.     int            i;
  212.     unsigned    int    prot;
  213.     int            firstPage;
  214.     int            lastPage;
  215.     unsigned    int    maxAddr;
  216.  
  217. #ifdef sun2
  218.     maxAddr = 0x1000000;
  219. #else
  220.     maxAddr = 0x10000000;
  221. #endif
  222.     if (dbgTraceLevel >= 5) {
  223.     printf("Dbg_InRange called with addr 0x%x %d bytes, and writable = %d\n",
  224.         addr, numBytes, (unsigned int) writeable);
  225.     }
  226.     /*
  227.      * Don't look at anything in device space. 
  228.      */
  229.     if (!(((addr + numBytes - 1) < VMMACH_DEV_START_ADDR) ||
  230.      (addr >= VMMACH_DMA_START_ADDR))) {
  231.     return FALSE;
  232.     }
  233.     if ((int) (addr) & 0x1) {
  234.     printf("Dbg: odd address: %x\n", addr);
  235.     return(FALSE);
  236.     }
  237. #ifndef FIRST_RUN
  238.     firstPage = ((unsigned int) addr) >> VMMACH_PAGE_SHIFT;
  239.     lastPage = (((unsigned int) addr) + numBytes - 1) >> VMMACH_PAGE_SHIFT;
  240.     for (i = firstPage; i <= lastPage; i++) {
  241.     pte = VmMachGetPageMap((Address)(i << VMMACH_PAGE_SHIFT));
  242.     if (dbgTraceLevel >= 5) {
  243.         printf("pte value was 0x%x\n", pte);
  244.     }
  245.     prot = pte & VMMACH_PROTECTION_FIELD;
  246.     if (!(pte & VMMACH_RESIDENT_BIT)) {
  247.         return(FALSE);
  248.     } else if (writeable) {
  249.         if (prot != VMMACH_KRW_PROT && prot != VMMACH_URW_PROT) {
  250.         return(FALSE);
  251.         }
  252.     } else {
  253.         if (prot != VMMACH_KRW_PROT && prot != VMMACH_URW_PROT &&
  254.         prot != VMMACH_KR_PROT && prot != VMMACH_UR_PROT) {
  255.         return(FALSE);
  256.         }
  257.     }
  258.     }
  259. #endif
  260.  
  261.     return(TRUE);
  262. }
  263.  
  264.  
  265. /*
  266.  * ----------------------------------------------------------------------------
  267.  *
  268.  * TranslateOpcode --
  269.  *
  270.  *     Return the string which describes the given opcode.
  271.  *
  272.  * Results:
  273.  *     The string which describes the given opcode.
  274.  *
  275.  * Side effects:
  276.  *     None.
  277.  *
  278.  * ----------------------------------------------------------------------------
  279.  */
  280. char *
  281. TranslateOpcode(opcode)
  282.     Dbg_Opcode opcode;        /* The opcode which is to be translated. */
  283. {
  284.     int index;
  285.  
  286.     index = (int) opcode;
  287.     if (index < 0 || index > (int) DBG_UNKNOWN) {
  288.         index = (int) DBG_UNKNOWN;
  289.     }
  290.  
  291.     return(opcodeNames[index]);
  292. }
  293.  
  294.  
  295. /*
  296.  * ----------------------------------------------------------------------------
  297.  *
  298.  * TranslateException --
  299.  *
  300.  *     Return the string that describes the given exception.
  301.  *
  302.  * Results:
  303.  *     None.
  304.  *
  305.  * Side effects:
  306.  *     None.
  307.  *
  308.  * ----------------------------------------------------------------------------
  309.  */
  310. char *
  311. TranslateException(exception)
  312.     int exception;        /* The exception which is to be translated. */
  313. {
  314.  
  315.     if (exception < 0 || exception > DBG_UNKNOWN_EXCEPT) {
  316.         exception = DBG_UNKNOWN_EXCEPT;
  317.     }
  318.  
  319.     return(exceptionNames[exception]);
  320. }
  321.  
  322.  
  323.  
  324.  
  325. /*
  326.  * ----------------------------------------------------------------------------
  327.  *
  328.  * Dbg_Init --
  329.  *
  330.  *     Initialize the debugger.
  331.  *
  332.  * Results:
  333.  *     None.
  334.  *
  335.  * Side effects:
  336.  *     dbgMonPC and dbgDoTrace are initialized.
  337.  *
  338.  * ----------------------------------------------------------------------------
  339.  */
  340. void
  341. Dbg_Init()
  342. {
  343.     dbgMonPC = 0;
  344.     dbgTraceLevel = 0;
  345.     dbgInDebugger = 0;
  346.     dbgIntPending = 0;
  347.     dbgPanic = FALSE;
  348.     dbg_BeingDebugged = FALSE;
  349.     machineType = 0;
  350.     Mach_MonPrintf("Machine type %d\n", machineType);
  351. }
  352.  
  353.  
  354. /*
  355.  * ----------------------------------------------------------------------------
  356.  *
  357.  * Dbg_InputPacket --
  358.  *
  359.  *     See if the current packet is for us.
  360.  *
  361.  * Results:
  362.  *     None.
  363.  *
  364.  * Side effects:
  365.  *     gotPacket is set to true if we got a packet that we liked.
  366.  *
  367.  * ----------------------------------------------------------------------------
  368.  */
  369. void
  370. Dbg_InputPacket(interPtr, packetPtr, packetLength)
  371.     Net_Interface    *interPtr;
  372.     Address        packetPtr;
  373.     int            packetLength;
  374. {
  375.     Address    dataPtr;
  376.     int        dataLength;
  377.     Net_EtherHdr    *etherHdrPtr;
  378.  
  379.     if (interPtr->netType != NET_NETWORK_ETHER) {
  380.     printf("Got a debugger packet on non-ethernet interface %s\n",
  381.         interPtr->name);
  382.     return;
  383.     }
  384.     etherHdrPtr = (Net_EtherHdr *)packetPtr;
  385.     if (etherHdrPtr->type != NET_ETHER_IP) {
  386.     if (dbgTraceLevel >= 5) {
  387.         printf("Non-IP (Type=0x%x) ", (int)etherHdrPtr->type);
  388.     }
  389.     return;
  390.     }
  391.     if (gotPacket) {
  392.     return;
  393.     }
  394.     if (dbgTraceLevel >= 4) {
  395.     printf("Validating packet\n");
  396.     }
  397.     { 
  398.     static char alignedBuffer[NET_ETHER_MAX_BYTES];
  399.         /*
  400.      * Make sure the packet starts on a 32-bit boundry so that we can
  401.      * use structures for describe the data.
  402.      */
  403.     if ( (unsigned int) (packetPtr + sizeof(Net_EtherHdr)) & 0x3 ) {
  404.           bcopy (packetPtr + sizeof(Net_EtherHdr), alignedBuffer,
  405.                 packetLength - sizeof(Net_EtherHdr));
  406.           packetPtr = alignedBuffer;
  407.     } else {
  408.           packetPtr = packetPtr + sizeof(Net_EtherHdr);
  409.     }
  410.  
  411.     if (Dbg_ValidatePacket(packetLength - sizeof(Net_EtherHdr),
  412.                    (Net_IPHeader *)(packetPtr),
  413.                    &dataLength, &dataPtr,
  414.                    &dbgMyIPAddr, &dbgSrcIPAddr, &dbgSrcPort)) {
  415.         if (dbgTraceLevel >= 4) {
  416.         printf("Got a packet: length=%d\n", dataLength);
  417.         }
  418.         bcopy((Address)etherHdrPtr, (Address)&dbgEtherHdr,
  419.             sizeof(Net_EtherHdr));
  420.         gotPacket = TRUE;
  421.         bcopy(dataPtr, requestBuffer, dataLength);
  422.         /*
  423.          * Set the interface we are using. 
  424.          */
  425.         dbgInterPtr = interPtr;
  426.     }
  427.     }
  428. }
  429.  
  430.  
  431. /*
  432.  * ----------------------------------------------------------------------------
  433.  *
  434.  * ReadRequest --
  435.  *
  436.  *     Read the next request from kdbx.
  437.  *
  438.  * Results:
  439.  *     None.
  440.  *
  441.  * Side effects:
  442.  *     TRUE if didn't time out.
  443.  *
  444.  * ----------------------------------------------------------------------------
  445.  */
  446. static Boolean
  447. ReadRequest(timeout)
  448.     Boolean    timeout;    /* TRUE if should timeout after waiting a 
  449.                  * while. */
  450. {
  451.     int    timeOutCounter;
  452.     Net_Interface    *interPtr;
  453.     int        i;
  454.  
  455.     gotPacket = FALSE;
  456.     timeOutCounter = dbgTimeout;
  457.     do {
  458.         DbgCheckNmis();
  459.         /*
  460.          * Listen on all the interfaces. The debugger is relatively
  461.          * stateless so its easiest to just listen on them all.
  462.          */
  463.         for (i = 0; ; i++) {
  464.         interPtr = Net_NextInterface(TRUE, &i);
  465.         if (interPtr == (Net_Interface *) NIL) {
  466.             break;
  467.         }
  468.         Net_RecvPoll(interPtr);
  469.         if (gotPacket) {
  470.             break;
  471.         }
  472.         }
  473.         if (timeout) {
  474.         timeOutCounter--;
  475.         }
  476.     } while(!gotPacket && timeOutCounter != 0);
  477.     if (gotPacket) {
  478.         replyOffset = PACKET_HDR_SIZE;
  479.         requestOffset = 4;
  480.         curMsgNum = *(int *)(requestBuffer);
  481.         if (dbgTraceLevel >= 4) {
  482.         printf("MsgNum = %d\n", curMsgNum);
  483.         }
  484.     }
  485.  
  486.     return(gotPacket);
  487. }
  488.  
  489.  
  490. /*
  491.  * ----------------------------------------------------------------------------
  492.  *
  493.  * GetRequestBytes --
  494.  *
  495.  *     Get the next numBytes bytes from the current request.
  496.  *
  497.  * Results:
  498.  *     None.
  499.  *
  500.  * Side effects:
  501.  *     None.
  502.  *
  503.  * ----------------------------------------------------------------------------
  504.  */
  505. static void
  506. GetRequestBytes(numBytes, dest)
  507.     int        numBytes;
  508.     Address    dest;
  509. {
  510.     bcopy(requestBuffer + requestOffset, dest, numBytes);
  511.     requestOffset += numBytes;
  512. }
  513.  
  514.  
  515. /*
  516.  * ----------------------------------------------------------------------------
  517.  *
  518.  * PutReplyBytes --
  519.  *
  520.  *     Put the given bytes into the reply buffer.
  521.  *
  522.  * Results:
  523.  *     None.
  524.  *
  525.  * Side effects:
  526.  *     None.
  527.  *
  528.  * ----------------------------------------------------------------------------
  529.  */
  530. static void
  531. PutReplyBytes(numBytes, src)
  532.     int        numBytes;
  533.     Address    src;
  534. {
  535.     if (replyOffset + numBytes > DBG_MAX_REPLY_SIZE) {
  536.     printf("PutReplyBytes: Buffer overflow\n");
  537.     numBytes = DBG_MAX_REPLY_SIZE - replyOffset;
  538.     }
  539.     bcopy(src, &replyBuffer[replyOffset], numBytes);
  540.     replyOffset += numBytes;
  541. }
  542.  
  543.  
  544. /*
  545.  * ----------------------------------------------------------------------------
  546.  *
  547.  * SendReply --
  548.  *
  549.  *     Send a reply to kdbx.
  550.  *
  551.  * Results:
  552.  *     None.
  553.  *
  554.  * Side effects:
  555.  *     None.
  556.  *
  557.  * ----------------------------------------------------------------------------
  558.  */
  559. static void
  560. SendReply()
  561. {
  562.     {
  563.     Net_EtherHdr        *etherHdrPtr;
  564.  
  565.     if (dbgTraceLevel >= 4) {
  566.         printf("Sending reply\n");
  567.     }
  568.     etherHdrPtr = (Net_EtherHdr *) (replyBuffer+2);
  569.     etherHdrPtr->source = dbgEtherHdr.destination;
  570.     etherHdrPtr->destination = dbgEtherHdr.source;
  571.     etherHdrPtr->type = dbgEtherHdr.type;
  572.     dbgGather.bufAddr = replyBuffer + sizeof(Net_EtherHdr)+2;
  573.     dbgGather.length = replyOffset - sizeof(Net_EtherHdr)-2;
  574.     dbgGather.mutexPtr = (Sync_Semaphore *) NIL;
  575.     bcopy((char *)&curMsgNum,(char *)(replyBuffer + PACKET_HDR_SIZE - 4),4);
  576.     Dbg_FormatPacket(dbgMyIPAddr, dbgSrcIPAddr, dbgSrcPort,
  577.              replyOffset - sizeof(Net_EtherHdr) - Dbg_PacketHdrSize()-2,
  578.              replyBuffer + sizeof(Net_EtherHdr) + 2);
  579.     Net_RawOutput(dbgInterPtr, (Address) etherHdrPtr, &dbgGather, 1);
  580.     if (dbgTraceLevel >= 4) {
  581.         printf("Sent reply\n");
  582.     }
  583.     }
  584. }
  585.  
  586.  
  587.  
  588. /*
  589.  * ----------------------------------------------------------------------------
  590.  *
  591.  * Dbg_Main --
  592.  *
  593.  *     The main debugger loop.  This will read commands from the network
  594.  *     and call the proper routine to execute them.
  595.  *
  596.  * Results:
  597.  *     None.
  598.  *
  599.  * Side effects:
  600.  *     None.
  601.  *
  602.  * ----------------------------------------------------------------------------
  603.  */
  604. /*ARGSUSED*/
  605. void
  606. Dbg_Main(trapType, trapStatePtr)
  607.     int            trapType;    /* The reason we were called. */
  608.     Mach_RegState    *trapStatePtr;    /* The CPU's state at the trap. */
  609. {
  610.     Boolean          done;        /* Boolean to tell us whether to leave
  611.                      * the main debugger loop */
  612.     Dbg_Opcode          opcode;            /* The operation that was requested */
  613.                     /* Process table entry that we switched
  614.                      * stacks to. */
  615.     Proc_ControlBlock    *procPtr = (Proc_ControlBlock *) NIL;
  616.     Boolean        atInterruptLevel;/* TRUE if we were entered from an
  617.                       * interrupt handler. */
  618.     static int         curContext;
  619.  
  620. #ifdef sun3
  621.     /*
  622.      * Turn on non-maskable interrupts.
  623.      */
  624.     Mach_MonStartNmi();
  625. #endif
  626. #ifndef FIRST_RUN
  627.     /*
  628.      * Switch to kernel context so that we can access the monitor.
  629.      */
  630.     curContext = oldContext = VmMachGetKernelContext();
  631.     VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  632. #endif
  633. #ifdef NOTDEF
  634. /*
  635.  * This is the code the other machine types execute to sync the disks
  636.  * when going into the debugger.  But it seems to cause us to pop out of the
  637.  * debugger, since it context switches to the backend write process.
  638.  * Why does it work (does it?) on the other machines?
  639.  */
  640.     if (!dbg_BeingDebugged) {
  641.     /*
  642.      * Try to sync the disks if we aren't at interrupt level.  If we
  643.      * are don't bother because we'll just hang waiting for interrupts.
  644.      * Of course I could force interrupts to be enabled but I'm not sure
  645.      * if that's a great idea.
  646.      */
  647.     if (mach_NumDisableIntrsPtr[0] == 0 && !mach_AtInterruptLevel) {
  648.         Mach_EnableIntr();
  649.         Sys_SyncDisks(MACH_CALL_DBG_TRAP);
  650.         dbg_SyncedDisks = TRUE;
  651.         Mach_DisableIntr();
  652.     }
  653.     }
  654. #endif NOTDEF
  655.  
  656.     dbg_InDebugger = TRUE;
  657.     /*
  658.      * Put us at interrupt level so that printf won't accidently enable
  659.      * interrupts.
  660.      */
  661.     atInterruptLevel = mach_AtInterruptLevel;
  662.     mach_AtInterruptLevel = TRUE;
  663.  
  664.     /*
  665.      * Force system log output to the console.
  666.      */
  667.     if (!syslogDiverted) {
  668.     Dev_SyslogDebug(TRUE);
  669.     }
  670.  
  671.     if (dbgPanic && DBG_CVT_MACH_TRAP(trapType) == DBG_BREAKPOINT_TRAP ) { 
  672.     dbgPanic = FALSE;
  673.     trapType = DBG_INTERRUPT;
  674.     /*
  675.      * Set the pc to the instruction after the trap.
  676.      */
  677.     trapStatePtr->pc = trapStatePtr->nextPc;
  678.     trapStatePtr->nextPc = trapStatePtr->nextPc+4;
  679.     } 
  680.     /*
  681.      * We want to inform the user what caused the problem.  However we only
  682.      * tell him if: 1) we are debugging the debugger; 2) we are not under 
  683.      * debugger control (i.e. we don't want to inform the user on every trace 
  684.      * trap), 3) we got something besides a trace trap or a breakpoint trap
  685.      * exception.
  686.      */
  687.     if (dbgTraceLevel >= 1 || !dbg_BeingDebugged || 
  688.         (DBG_CVT_MACH_TRAP(trapType) != DBG_BREAKPOINT_TRAP)) { 
  689.     Dev_VidEnable(TRUE);    /* unblank the screen */
  690.     printf("Entering debugger with a %s (%d) exception at PC 0x%x\r\n",
  691.            TranslateException(DBG_CVT_MACH_TRAP(trapType)),trapType,
  692.            (unsigned) trapStatePtr->pc);
  693.     }
  694.  
  695.  
  696.     /*
  697.      * Inform the network module that we're in charge now.
  698.      */
  699.     dbg_UsingNetwork = TRUE;
  700.     /*
  701.      * If we are stopped after a continue or single step must write a
  702.      * null byte to the debugger at the other end.  It knows that if it sees
  703.      * a null byte we are stopped at this end.
  704.      */
  705.     if (dbg_BeingDebugged) {
  706.         unsigned        char    ch;
  707.     int    timeout = 5;
  708.         ch = 0;
  709.         PutReplyBytes(1, (Address)&ch);
  710.         SendReply();
  711.         do {
  712.             if (ReadRequest(TRUE)) {
  713.                 GetRequestBytes(4, (Address)&opcode);
  714.         if (opcode != DBG_CONTINUE) {
  715.             break;
  716.         } else {
  717.             PutReplyBytes(4, (Address) &opcode);
  718.             SendReply();
  719.             continue;
  720.         }
  721.             }
  722.             /*
  723.              * We can only timeout if we are using network debugging.
  724.              */
  725.         Net_RawOutput(dbgInterPtr, (Address) replyBuffer, 
  726.             &dbgGather, 1);
  727.             if (dbgTraceLevel >= 5) {
  728.                 printf("DBG: Timeout\n");
  729.             }
  730.             printf("TI ");
  731.         } while (timeout-- > 0);
  732.     } else {
  733.          short    t_opcode;
  734.      /*
  735.       * The kmsg program still sends short opcodes. If the top 16 bits
  736.       * are zero we assume that it is a long opcode.
  737.       */
  738.         (void) ReadRequest(FALSE);
  739.         GetRequestBytes(2, (Address)&t_opcode);
  740.     if (t_opcode == 0) {
  741.         GetRequestBytes(2, (Address)&t_opcode);
  742.     }
  743.     opcode = (Dbg_Opcode) t_opcode;
  744.  
  745.     }
  746.  
  747.     /*
  748.      * Now read commands until kdbx tells us that we can return.
  749.      */
  750.     done = FALSE;
  751.     while (!done) {
  752.     if (dbgTraceLevel >= 2) {
  753.         printf("Request: %s ", TranslateOpcode(opcode));
  754.     }
  755.  
  756.     /*
  757.      * Process the request 
  758.      */
  759.     switch (opcode) {
  760.  
  761.         /*
  762.          * The client wants to read some data from us ...
  763.          */
  764.  
  765.         case DBG_GET_STOP_INFO: {
  766.         StopInfo    stopInfo;
  767.         stopInfo.codeStart = (int)mach_CodeStart;
  768.         if (procPtr != (Proc_ControlBlock *) NIL &&
  769.             procPtr->machStatePtr != (Mach_State *)NIL) {
  770.             stopInfo.regs = *(procPtr->machStatePtr->switchRegs);
  771.             stopInfo.regs.tbr = trapStatePtr->tbr;
  772.             stopInfo.regs.y = trapStatePtr->y;
  773.             stopInfo.regs.pc = ((int) &Mach_ContextSwitch)+16;
  774.             stopInfo.regs.nextPc = stopInfo.regs.pc+4;
  775.  
  776.         } else {
  777.             stopInfo.regs = *trapStatePtr;
  778.         }
  779.         stopInfo.trapType = trapType;
  780.         PutReplyBytes(sizeof(stopInfo), (Address)&stopInfo);
  781.         SendReply();
  782.         break;
  783.         }
  784.         case DBG_READ_ALL_REGS: 
  785.  
  786.         if (procPtr != (Proc_ControlBlock *) NIL &&
  787.             procPtr->machStatePtr != (Mach_State *)NIL) {
  788.             Mach_RegState    regState;
  789.             regState = *(procPtr->machStatePtr->switchRegs);
  790.             regState.tbr = trapStatePtr->tbr;
  791.             regState.y = trapStatePtr->y;
  792.             regState.pc = ((int) &Mach_ContextSwitch)+16;
  793.             regState.nextPc = regState.pc+4;
  794.             PutReplyBytes(sizeof(regState), (Address) ®State);
  795.         } else {
  796.             PutReplyBytes(sizeof(*trapStatePtr),
  797.                      (Address) trapStatePtr);
  798.         }
  799.         SendReply();
  800.         break;
  801.  
  802.         case DBG_GET_DUMP_BOUNDS: {
  803.         Dbg_DumpBounds bounds;
  804.         extern unsigned int end;
  805.         bounds.pageSize = vm_PageSize;
  806.         bounds.stackSize = mach_KernStackSize;
  807.         bounds.kernelCodeStart = (unsigned int) mach_KernStart;
  808.         bounds.kernelCodeSize  = 
  809.             (unsigned int) (((Address)(&end)) - mach_KernStart);
  810.         bounds.kernelDataStart    = ((unsigned int)(&end));
  811.         bounds.kernelDataSize    = (unsigned int) 
  812.                 (vmMemEnd - ((Address)(&end)));
  813.         bounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  814.         bounds.kernelStacksSize = (unsigned int) 
  815.                 (vmStackEndAddr - vmStackBaseAddr);
  816.         bounds.fileCacheStart    = (unsigned int)vmBlockCacheBaseAddr;
  817.         bounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr - 
  818.                         vmBlockCacheBaseAddr);
  819.  
  820.         PutReplyBytes(sizeof(bounds), (char *)&bounds);
  821.         SendReply();
  822.         break;
  823.         }
  824.  
  825.         case DBG_GET_VERSION_STRING: {
  826.         char    *version;
  827.  
  828.         version = SpriteVersion();
  829.         PutReplyBytes(strlen(version) + 1, version);
  830.         SendReply();
  831.         break;
  832.         }
  833.         
  834.         case DBG_INST_READ:
  835.         case DBG_DATA_READ: {
  836.         Dbg_ReadMem    readMem;
  837.         int        status;
  838.  
  839.         GetRequestBytes(sizeof(readMem), (Address) &readMem); 
  840.         if (dbgTraceLevel >= 2) {
  841.             printf("Addr=%x Numbytes=%d ",
  842.                 readMem.address, readMem.numBytes);
  843.         }
  844. #ifndef FIRST_RUN
  845.         VmMachSetKernelContext(curContext);
  846. #endif
  847.         if (Dbg_InRange((unsigned int) readMem.address, readMem.numBytes,
  848.                 FALSE)) {
  849.             status = 1;
  850.             PutReplyBytes(sizeof(status), (Address)&status);
  851.             PutReplyBytes(readMem.numBytes, (Address)readMem.address);
  852.         } else {
  853.             if (dbgTraceLevel >= 2) {
  854.             printf("FAILURE ");
  855.             }
  856.             status = 0;
  857.             PutReplyBytes(sizeof(status), (Address)&status);
  858.         }
  859. #ifndef FIRST_RUN
  860.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  861. #endif
  862.         SendReply();
  863.         break;
  864.         }
  865.  
  866.         /*
  867.          * The client wants to write something to us.
  868.          */
  869.         case DBG_SET_PID: {
  870.         Proc_PID    pid;
  871.  
  872.         GetRequestBytes(sizeof(pid), (Address) &pid);
  873.          {
  874.             int    dummy;
  875.  
  876.             PutReplyBytes(4, (Address) &dummy);
  877.             SendReply();
  878.         }
  879.         if (dbgTraceLevel >= 2) {
  880.             printf("pid %x ", pid);
  881.         }
  882.         if (pid == 0) {
  883.             procPtr = (Proc_ControlBlock *) NIL;
  884.             curContext = oldContext;
  885.         } else {
  886.             procPtr = Proc_GetPCB(pid);
  887.             if (procPtr == (Proc_ControlBlock *) NIL ||
  888.                 procPtr == (Proc_ControlBlock *) 0 ||
  889.             procPtr->state == PROC_UNUSED ||
  890.                 procPtr->state == PROC_DEAD ||
  891.             procPtr->state == PROC_NEW) {
  892.             printf("Can't backtrace stack for process %x\n",
  893.                     pid);
  894.             procPtr = (Proc_ControlBlock *) NIL;
  895.             } else {
  896.             curContext = VmMach_GetContext(procPtr);
  897.             if (curContext == -1) {
  898.                 printf("No user context loaded for pid 0x%x\n", 
  899.                    pid);
  900.                 curContext = VMMACH_KERN_CONTEXT;
  901.             }
  902.             }
  903.         }
  904.         break;
  905.         }
  906.         case DBG_REBOOT: {
  907.         int    stringLength;
  908.         char    rebootString[100];
  909.         /*
  910.          * For a reboot command first read the size of the string and
  911.          * then the string itself.
  912.          */
  913.         GetRequestBytes(sizeof(int), (Address)&stringLength);
  914.         if (stringLength != 0) {
  915.             GetRequestBytes(stringLength, (Address)rebootString);
  916.         }
  917.         rebootString[stringLength] = '\0';
  918.          {
  919.             int    dummy;
  920.  
  921.             PutReplyBytes(4, (Address) &dummy);
  922.             SendReply();
  923.         }
  924.         Mach_MonReboot(rebootString);
  925.         }
  926.         case DBG_INST_WRITE:
  927.         case DBG_DATA_WRITE: {
  928.         Dbg_WriteMem        writeMem;
  929.         unsigned    char    ch;
  930.         /*
  931.          * For an instruction or a data write we first have to find out 
  932.          * which address to write to and how many bytes to write.  Next
  933.          * we have to make sure that the address is valid.  If it is
  934.          * then we read the data and write it to the given address.  If
  935.          * not we just report an error to kdbx.
  936.          */
  937.         GetRequestBytes(2 * sizeof(int), (Address) &writeMem);
  938.         if (dbgTraceLevel >= 2) {
  939.             printf("Addr=%x Numbytes=%d ",
  940.                 writeMem.address, writeMem.numBytes);
  941.         }
  942.  
  943. #ifndef FIRST_RUN
  944.         VmMachSetKernelContext(curContext);
  945. #endif    
  946.         if (Dbg_InRange((unsigned int) writeMem.address,
  947.                 writeMem.numBytes, opcode == DBG_DATA_WRITE)) {
  948. #ifndef FIRST_RUN
  949.             if (opcode == DBG_INST_WRITE) {
  950.             VmMach_SetProtForDbg(TRUE, writeMem.numBytes, 
  951.                          (Address)writeMem.address);
  952.             }
  953. #endif
  954.             GetRequestBytes(writeMem.numBytes,
  955.                     (Address) writeMem.address);
  956. #ifndef FIRST_RUN
  957.             if (opcode == DBG_INST_WRITE) {
  958.             VmMach_SetProtForDbg(FALSE, writeMem.numBytes, 
  959.                          (Address)writeMem.address);
  960.             }
  961. #endif
  962.             ch = 1;
  963.         } else {
  964.             char    buf[100];
  965.  
  966.             if (dbgTraceLevel >= 2) {
  967.             printf("FAILURE ");
  968.             }
  969.             GetRequestBytes(writeMem.numBytes, buf);
  970.             ch = 0;
  971.         }
  972. #ifndef FIRST_RUN
  973.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  974. #endif
  975.  
  976.         PutReplyBytes(1, (char *) &ch);
  977.         SendReply();
  978.  
  979.         break;
  980.         }
  981.  
  982.         case DBG_WRITE_REG: {                
  983.         Dbg_WriteReg    writeReg;
  984.  
  985.         /*
  986.          * First find out which register is being written and
  987.          * then read the value.
  988.          */
  989.         GetRequestBytes(sizeof(writeReg), (Address)&writeReg);
  990.          {
  991.             int    dummy;
  992.  
  993.             PutReplyBytes(4, (Address) &dummy);
  994.             SendReply();
  995.         }
  996.         if (dbgTraceLevel >= 2) {
  997.             printf("register %d data %x ", writeReg.regNum, 
  998.                 writeReg.regVal);
  999.         }
  1000.         ((int *) trapStatePtr)[(writeReg.regNum)] = writeReg.regVal;
  1001.         break;
  1002.         }
  1003.  
  1004.         case DBG_DIVERT_SYSLOG: 
  1005.         GetRequestBytes(sizeof(Boolean), (Address)&syslogDiverted);
  1006.          {
  1007.             int    dummy;
  1008.  
  1009.             PutReplyBytes(4, (Address) &dummy);
  1010.             SendReply();
  1011.         }
  1012.         break;
  1013.  
  1014.         case DBG_BEGIN_CALL: {
  1015.         /*
  1016.          * We are beginning a call command.  Fix up the stack
  1017.          * so that we will be able to continue.  We will put
  1018.          * it back when we are done.
  1019.          */
  1020.         int    dummy;
  1021.         if (dbgCanUseSyslog) {
  1022.             dbg_UsingSyslog = TRUE;
  1023.         }
  1024.  
  1025.         PutReplyBytes(4, (Address) &dummy);
  1026.         SendReply();
  1027.  
  1028.         break;
  1029.         }
  1030.         case DBG_END_CALL: {
  1031.         char    *buffer;
  1032.         int    *firstIndexPtr;
  1033.         int    *lastIndexPtr;
  1034.         int    bufSize;
  1035.         int    length;
  1036.         /*
  1037.          * Dump the syslog buffer.
  1038.          */
  1039.         Dev_SyslogReturnBuffer(&buffer, &firstIndexPtr,
  1040.                        &lastIndexPtr, &bufSize);
  1041. /* #ifdef GOOD_SYSLOG */
  1042.         if (*firstIndexPtr == -1) {
  1043.             length = 0;
  1044.             PutReplyBytes(4, (Address) &length);
  1045.             dbg_UsingSyslog = FALSE;
  1046.         } else if (*firstIndexPtr <= *lastIndexPtr) {
  1047.             length = *lastIndexPtr - *firstIndexPtr + 1;
  1048.             if (length + 4 > PACKET_DATA_SIZE) {
  1049.             length = PACKET_DATA_SIZE - 4;
  1050.             }
  1051.             PutReplyBytes(4, (Address) &length);
  1052.             PutReplyBytes(length,
  1053.                   (Address)&buffer[*firstIndexPtr]);
  1054.             *firstIndexPtr += length;
  1055.             if (*firstIndexPtr > *lastIndexPtr) {
  1056.             *firstIndexPtr = *lastIndexPtr = -1;
  1057.             }
  1058.         } else {
  1059.             length = bufSize - *firstIndexPtr;
  1060.             if (length + 4 > PACKET_DATA_SIZE) {
  1061.             length = PACKET_DATA_SIZE - 4;
  1062.             }
  1063.             PutReplyBytes(4, (Address) &length);
  1064.             PutReplyBytes(length,
  1065.                   (Address)buffer[*firstIndexPtr]);
  1066.             *firstIndexPtr += length;
  1067.             if (*firstIndexPtr == bufSize) {
  1068.             *firstIndexPtr = 0;
  1069.             }
  1070.         }
  1071. #ifdef notdef
  1072.         length = 0;
  1073.         PutReplyBytes(4, (Address) &length);
  1074.         dbg_UsingSyslog = FALSE;
  1075. #endif
  1076.         SendReply();
  1077.         break;
  1078.         }
  1079.         case DBG_CALL_FUNCTION: {
  1080.         Dbg_CallFunc        callFunc;
  1081.         int            returnVal;
  1082.         static int        argBuf[128];
  1083.         GetRequestBytes(2 * sizeof(int), (Address) &callFunc);
  1084.         if (dbgTraceLevel >= 2) {
  1085.             printf("Addr=%x Numbytes=%d ",
  1086.                 callFunc.address, callFunc.numBytes);
  1087.         }
  1088.         VmMachSetKernelContext(curContext);
  1089.         if ((callFunc.numBytes >= 0 && callFunc.numBytes < 128) &&
  1090.              Dbg_InRange((unsigned int) callFunc.address,4,FALSE)) {
  1091.             GetRequestBytes(callFunc.numBytes,(Address) argBuf);
  1092.             returnVal = (* ((int (*)()) callFunc.address))(argBuf[0],
  1093.             argBuf[1],argBuf[2],argBuf[3],argBuf[4],argBuf[5],argBuf[6],
  1094.             argBuf[7],argBuf[8],argBuf[9]);
  1095.         } else {
  1096.  
  1097.             if (dbgTraceLevel >= 2) {
  1098.             printf("FAILURE ");
  1099.             }
  1100.             GetRequestBytes(callFunc.numBytes,(Address)argBuf);
  1101.             returnVal = -1;
  1102.         }
  1103.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  1104.         PutReplyBytes(4, (char *) &returnVal);
  1105.         SendReply();
  1106.  
  1107.         break;
  1108.         }
  1109.         case DBG_CONTINUE: {
  1110.         /*
  1111.          * The client wants to continue execution.
  1112.          */
  1113.         int    foo;
  1114.         GetRequestBytes(sizeof(int), 
  1115.                 (Address) &foo);
  1116.         if (dbgTraceLevel >= 2) {
  1117.             printf("Continuing from pc %x ",
  1118.                 trapStatePtr->pc);
  1119.         }
  1120.         {
  1121.             int    dummy;
  1122.  
  1123.             PutReplyBytes(4, (Address) &dummy);
  1124.             SendReply();
  1125.         }
  1126.  
  1127.         dbg_BeingDebugged = TRUE;
  1128.         done = TRUE;
  1129.         break;
  1130.         }
  1131.         case DBG_SINGLESTEP: {
  1132.         /*
  1133.          * The client wants to single step.
  1134.          */
  1135.         int    dummy;
  1136.         GetRequestBytes(sizeof(int),  (Address) &dummy);
  1137.         printf("Sun4's can't single step\n");
  1138.  
  1139.             PutReplyBytes(4, (Address) &dummy);
  1140.         SendReply();
  1141.  
  1142.         break;
  1143.         }
  1144.         case DBG_DETACH:
  1145.         /*
  1146.          * The debugger has terminated and wants to let us go about our
  1147.          * business.
  1148.          */
  1149.         if (dbgTraceLevel >= 2) {
  1150.             printf("Detaching at pc %x ",
  1151.                 trapStatePtr->pc);
  1152.         }
  1153.             {
  1154.             int    dummy;
  1155.  
  1156.             PutReplyBytes(4, (Address) &dummy);
  1157.             SendReply();
  1158.         }
  1159.  
  1160.         dbg_BeingDebugged = FALSE;
  1161.         done = TRUE;
  1162.         printf("Sprite is now detached from the debugger\r\n");
  1163.         break;
  1164.  
  1165.         case DBG_UNKNOWN:
  1166.         printf("debugger: unrecognized request\n");
  1167.         break;
  1168.     }
  1169.  
  1170.     if (dbgTraceLevel >= 2) {
  1171.         printf("\r\n");
  1172.     }
  1173.     if (!done) {
  1174.          short    t_opcode;
  1175.          /*
  1176.           * The kmsg program still sends short opcodes. If the top 16 bits
  1177.           * are zero we assume that it is a long opcode.
  1178.           */
  1179.         (void) ReadRequest(FALSE);
  1180.         GetRequestBytes(2, (Address)&t_opcode);
  1181.         if (t_opcode == 0) {
  1182.         GetRequestBytes(2, (Address)&t_opcode);
  1183.         }
  1184.         opcode = (Dbg_Opcode) t_opcode;
  1185.     }
  1186.     }
  1187.  
  1188.  
  1189. #ifndef FIRST_RUN
  1190.     VmMachSetKernelContext(oldContext);
  1191. #endif
  1192.     mach_AtInterruptLevel = atInterruptLevel;
  1193.     dbg_UsingNetwork = FALSE;
  1194.  
  1195.     /*
  1196.      * Don't force system log output to the console.
  1197.      */
  1198.     if (!syslogDiverted) {
  1199.     Dev_SyslogDebug(FALSE);
  1200.     }
  1201. #ifdef sun3
  1202.     /*
  1203.      * Turn off non-maskable interrupts.
  1204.      */
  1205.     Mach_MonStopNmi();
  1206. #endif
  1207. }
  1208.